from google.appengine.ext import db
import datetime
import urllib
from xml.dom import minidom

app_id = 'your yahoo app id here'

months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

class Woeid(db.Model):
    zip_code = db.StringProperty(required=True)
    woeid = db.StringProperty(required=True)

class Forecast(db.Model):
    zip_code = db.StringProperty(required=True)
    timestamp = db.DateProperty(required=True)
    high_temp = db.IntegerProperty(required=True)
    low_temp = db.IntegerProperty(required=True)
    conditions = db.StringProperty(required=True)
    condition_code = db.IntegerProperty(required=True)
    
def get_forecasts_db(zip_code):
    # get current date to compare to database
    current_date = datetime.datetime.now().date()
    
    # get first 2 forecasts in db that are greater than or equal the current date
    fc_query= db.GqlQuery("SELECT * FROM Forecast WHERE timestamp >= :1 AND zip_code = :2",
                          current_date, zip_code)
    forecasts = fc_query.fetch(2)
    
    # if there is at least 1 return today and tomorrow
    if len(forecasts) > 1:
        return forecasts
    
    # get forecasts from Yahoo
    forecasts = get_forecasts_yahoo(zip_code)
    
    for f in forecasts:
        query = db.GqlQuery("SELECT * FROM Forecast WHERE timestamp = :1 AND zip_code = :2",
                 f.timestamp, zip_code)
        results = query.fetch(1)
        if len(results) < 1:
            f.put()
    
    return forecasts

def parse_date(d):
    ar = d.split(' ')
    month = 1
    for m in months:
        if m == ar[1]:
            break
        month = month + 1
    return datetime.date(int(ar[2]), int(month), int(ar[0]))
    
def get_forecasts_yahoo(zip_code):
    woeid = get_woeid(zip_code)
    if woeid == None:
        return None
    
    weatherns = 'http://xml.weather.yahoo.com/ns/rss/1.0'
    url = 'http://weather.yahooapis.com/forecastrss?w=%s' % woeid
    data = urllib.urlopen(url).read()
    dom = minidom.parseString(data)
    forecasts = dom.getElementsByTagNameNS(weatherns, 'forecast')
    
    if len(forecasts) > 0:
        fcs = []
        for f in forecasts:
            hi = f.getAttribute('high')
            lo = f.getAttribute('low')
            text = f.getAttribute('text')
            code = f.getAttribute('code')
            stamp = parse_date(f.getAttribute('date'))
            fc = Forecast(
                zip_code = zip_code,
                timestamp = stamp,
                high_temp = int(hi),
                low_temp = int(lo),
                conditions = text,
                condition_code = int(code)
            )
            fcs.append(fc)
        return fcs
    else:
        return None
    
def get_woeid(zip_code):
    # create query (yes, the placeholders are 1 indexed!)
    query = db.GqlQuery("SELECT * FROM Woeid WHERE zip_code = :1", zip_code)
    results = query.fetch(1)
    if len(results) == 1:
        return results[0].woeid
    else:
        add_woeid(zip_code)
        results = query.fetch(1)
        return results[0].woeid

def add_woeid(zip_code):
    # create url
    url = 'http://where.yahooapis.com/v1/places.q(%s)?appid=%s' % (zip_code, app_id)
    # get xml
    data = urllib.urlopen(url).read()
    # create dom
    dom = minidom.parseString(data)
    # get woeid
    woeid = dom.getElementsByTagName('woeid')[0].firstChild.nodeValue
    # create db record
    w = Woeid(zip_code=zip_code, woeid=woeid)
    w.put()
    print '%s - %s' % (zip_code, woeid)